﻿using System;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;
using System.Globalization;
using System.Timers;
using System.Runtime.InteropServices;

namespace GroundStation
{
    public partial class Form1 : Form
    {
        Telemetry tele = new Telemetry();
        ArtificialHorizon ah = new ArtificialHorizon();

        int offsetX = 0;
        int offsetY = 0;
        bool moving = false;
        Map map;
        private fdr.SDlogger sdlog;
        private fdr.ClearSD clearSD;
        private bool isfdr = false;

        private static System.Timers.Timer timerRead;
        private static System.Timers.Timer timerDraw;
        private static System.Windows.Forms.Timer timerSD;

        private string selectedComPort = null;
        private string selectedSDDrive = null;

        delegate void SetBoolEnabled(bool componentState);

        public Form1()
        {
            InitializeComponent();
            portsRefs(null);
            tsStatusLabel.Text = Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + "..";
            map = new Map(tsStatusLabel.Text);
            ah.Init(pictureBoxArtificialHorizon);
            map.Init(pbMap);
            map.ZoomIn();
            map.ZoomOut();

            timerDraw = new System.Timers.Timer(50);
            timerDraw.Elapsed += new ElapsedEventHandler(timerDraw_Tick);

            timerRead = new System.Timers.Timer(100);
            timerRead.Elapsed += new ElapsedEventHandler(timerRead_Tick);

            timerSD = new System.Windows.Forms.Timer();
            timerSD.Interval = 100;
            timerSD.Tick += new EventHandler(timerSD_Tick);

            map.Update();

            map.AddCoord(tele.PosX, tele.PosY);

            timerDraw.Enabled = true;
        }

        private bool portsRefs(string setPort)
        {
            selectedComPort = null;
            portToolStripMenuItem.DropDownItems.Clear();
            string[] ports = SerialPort.GetPortNames();
            foreach (string port in ports)
            {
                ToolStripMenuItem item = new ToolStripMenuItem(port, null, menuPortsClick);
                if (port == setPort)
                {
                    item.Checked = true;
                    selectedComPort = port;
                }
                portToolStripMenuItem.DropDown.Items.Add(item);
            }
            if (selectedComPort == null && ports.Length > 0)
            {
                selectedComPort = ports[ports.Length - 1];
                ToolStripMenuItem item = (ToolStripMenuItem)portToolStripMenuItem.DropDownItems[ports.Length - 1];
                item.Checked = true;
            }
            return true;
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            systemStop();
        }

        private void timerDraw_Tick(object sender, EventArgs e)
        {
            timerDraw.Enabled = false;
            ah.Draw(tele.EulPitch, tele.EulRoll, tele.EulHeading, tele.AdcSpeed, tele.AdcAlt);
            map.Update();
            timerDraw.Enabled = true;
        }

        private void timerSD_Tick(object sender, EventArgs e)
        {
            timerSD.Stop();
            if (isfdr)
            {
                if (sdlog != null && !sdlog.SDIsRunning())
                {
                    isfdr = false;
                }
                else if (clearSD != null && !clearSD.isClearSDin())
                {
                    isfdr = false;
                }
                timerSD.Start();
            }
            else
            {
                sdProgress.Style = ProgressBarStyle.Blocks;
                logsToolStripMenuItem.Enabled = true;
                isfdr = false;
                clearSD = null;
                sdlog = null;
            }
        }

        private void timerRead_Tick(object sender, EventArgs e)
        {
            timerRead.Enabled = false;

            lblSysTime.Text = TimeSpan.FromMilliseconds((double)tele.Time).ToString();//@"h\:mm\:ss"); // .net 4 required // tele.Time.ToString(); needed by .net 3.5
            lblAdcSpeed.Text = tele.AdcSpeed.ToString("0.00", CultureInfo.InvariantCulture);
            lblAdcAlt.Text = tele.AdcAlt.ToString("0.00", CultureInfo.InvariantCulture);
            lblAdcTemp.Text = tele.AdcTemp.ToString("0.00", CultureInfo.InvariantCulture);
            lblVolt1.Text = tele.PwrVolt1.ToString("0.00", CultureInfo.InvariantCulture);
            lblVolt2.Text = tele.PwrVolt2.ToString("0.00", CultureInfo.InvariantCulture);
            lblVolt3.Text = tele.PwrVolt3.ToString("0.00", CultureInfo.InvariantCulture);
            lblVolt4.Text = tele.PwrVolt4.ToString("0.00", CultureInfo.InvariantCulture);
            lblFuel.Text = tele.PwrFuel.ToString("0.00", CultureInfo.InvariantCulture);
            lblRpm.Text = tele.EmsRmp.ToString("0.00", CultureInfo.InvariantCulture);
            lblHeadTemp.Text = tele.EmsTempHead.ToString("0.00", CultureInfo.InvariantCulture);
            lblExhaustTemp.Text = tele.EmsTempExhaust.ToString("0.00", CultureInfo.InvariantCulture);

            timerDraw.Enabled = false;
            map.AddCoord(tele.PosX, tele.PosY);
            timerDraw.Enabled = true;

            timerRead.Enabled = true;
        }

        private void pbMap_MouseDown(object sender, MouseEventArgs e)
        {
            moving = true;
            offsetX = e.X;
            offsetY = e.Y;
            //map.AddOffset(offsetX, offsetY);
        }

        private void pbMap_MouseMove(object sender, MouseEventArgs e)
        {
            // not finished yet - TODO

            if (moving)
            {
                offsetX -= e.X;
                offsetY -= e.Y;
                map.AddOffset(offsetX, offsetY);
                offsetX = e.X;
                offsetY = e.Y;
            }//*/
        }

        private void pbMap_MouseUp(object sender, MouseEventArgs e)
        {
            moving = false;
        }

        private void buttonZoomIn_Click(object sender, EventArgs e)
        {
            map.ZoomIn();
        }

        private void buttonZoomOut_Click(object sender, EventArgs e)
        {
            map.ZoomOut();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void systemStop()
        {
            tele.Stop();
            map.Stop();
            if (clearSD != null)
                clearSD.Stop();
            if (sdlog != null)
                sdlog.SDStop();
        }

        private void connectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            startTelemetry();
        }

        private void startTelemetry()
        {
            if (connectToolStripMenuItem.Text.ToString() == "Connect")
            {
                if (selectedComPort != null)
                {
                    tele.Init(selectedComPort);
                    connectToolStripMenuItem.Text = "Disconnect";
                    portToolStripMenuItem.Enabled = false;
                    timerRead.Enabled = true;
                }
                else
                    System.Windows.Forms.MessageBox.Show("Com port not set!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else
            {
                connectToolStripMenuItem.Text = "Connect";
                portToolStripMenuItem.Enabled = true;
                tele.Stop();
                timerRead.Enabled = false;
            }
        }

        private void aboutGroundStationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Windows.Forms.MessageBox.Show(this, "blablabla", "BlaBla", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        private void menuPortsClick(object sender, EventArgs e)
        {
            portsRefs(sender.ToString());//, false);
            connectionToolStripMenuItem.ShowDropDown();
            portToolStripMenuItem.ShowDropDown();
            portToolStripMenuItem.Select();
        }

        private void tsStatusLabel_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fbdMapPath = new FolderBrowserDialog();
            fbdMapPath.SelectedPath = this.tsStatusLabel.Text;
            if (fbdMapPath.ShowDialog() == DialogResult.OK)
            {
                this.tsStatusLabel.Text = fbdMapPath.SelectedPath;
                map.MapFolder = this.tsStatusLabel.Text;
                map.ZoomIn();
                map.ZoomOut();
                //if(!map.Change) map.Change = true; // TODO instead of zoomin zoomout...
            }
        }

        private void fileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();
            openFileDialog1.FilterIndex = 2;
            openFileDialog1.RestoreDirectory = true;

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    string file;
                    this.Cursor = Cursors.WaitCursor;
                    if ((file = openFileDialog1.FileName) != null)
                    {
                        sdlog = new fdr.SDlogger(file, false);
                        logsToolStripMenuItem.Enabled = false;
                        sdProgress.Style = ProgressBarStyle.Marquee;
                        isfdr = true;
                        timerSD.Start();
                    }
                    this.Cursor = Cursors.Default;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(DateTime.Now.ToLongTimeString() + "=> error: Could not read file from disk.\r\n\tOriginal error=> " + ex.Message);
                }
            }
        }

        private void logsToolStripMenuItem_DropDownOpening(object sender, EventArgs e)
        {
            sdReadToolStripMenuItem.DropDownItems.Clear();
            sdClearToolStripMenuItem.DropDownItems.Clear();
            string[] drives = Environment.GetLogicalDrives();
            foreach (string drive in drives)
            {
                System.IO.DriveInfo di = new System.IO.DriveInfo(drive);
                if (di.DriveType == DriveType.Removable)
                {
                    try
                    {
                        string diff;
                        {
                            diff = di.DriveFormat;
                        }
                    }
                    catch// (IOException ex)
                    {
                        if (Marshal.GetLastWin32Error() == 1005)
                        {
                            ToolStripMenuItem item = new ToolStripMenuItem(drive, null, menuSdReadClick);
                            sdReadToolStripMenuItem.DropDownItems.Add(item);
                            ToolStripMenuItem item2 = new ToolStripMenuItem(drive, null, menuSdClearClick);
                            ToolStripMenuItem item3 = new ToolStripMenuItem(drive + " TotalClear", null, menuSdTotalClearClick);
                            item2.DropDown.Items.Add(item3);
                            sdClearToolStripMenuItem.DropDownItems.Add(item2);
                        }
                    }
                }
            }
        }

        private void menuSdReadClick(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            selectedSDDrive = sender.ToString();
            if (selectedSDDrive == null)
            {
                // dialogové okno - není vybrána korektní karta?
            }
            else
            {
                sdlog = new fdr.SDlogger(selectedSDDrive, true);
                if (sdlog.SDIsRunning())
                {
                    logsToolStripMenuItem.Enabled = false;
                    sdProgress.Style = ProgressBarStyle.Marquee;
                    isfdr = true;
                    timerSD.Start();
                }
                //else
                //    throw new Exception("SD reading thread: Was not able to start fast enought.");
            }
            this.Cursor = Cursors.Default;
        }

        private void menuSdClearClick(object sender, EventArgs e)
        {
            logsToolStripMenuItem.HideDropDown();
            this.Cursor = Cursors.WaitCursor;
            selectedSDDrive = sender.ToString();
            if (selectedSDDrive == null)
            {
                // dialogové okno - není vybrána korektní karta?
            }
            else
            {
                clearSD = new fdr.ClearSD(selectedSDDrive);
                if (clearSD.isClearSDin())
                {
                    logsToolStripMenuItem.Enabled = false;
                    sdProgress.Style = ProgressBarStyle.Marquee;
                    isfdr = true;
                    timerSD.Start();
                }
                //else
                //    throw new Exception("SD clearing thread: Was not able to start fast enought.");
            }
            this.Cursor = Cursors.Default;
        }

        private void menuSdTotalClearClick(object sender, EventArgs e)
        {
            logsToolStripMenuItem.HideDropDown();
            this.Cursor = Cursors.WaitCursor;
            selectedSDDrive = sender.ToString();
            if (selectedSDDrive == null)
            {
                // dialogové okno - není vybrána korektní karta?
            }
            else
            {
                clearSD = new fdr.ClearSD(selectedSDDrive, true);
                if (clearSD.isClearSDin())
                {
                    logsToolStripMenuItem.Enabled = false;
                    sdProgress.Style = ProgressBarStyle.Marquee;
                    isfdr = true;
                    timerSD.Start();
                }
                //else
                //    throw new Exception("SD clearing thread: Was not able to start fast enought.");
            }
            this.Cursor = Cursors.Default;
        }
    }
}
